package com.polaris.live.im.manager

import androidx.annotation.MainThread
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.util.LogExt
import com.polaris.live.common.util.StructUtils
import com.polaris.live.im.db.database.AppDatabase
import com.polaris.live.im.db.entity.MessageEntity
import com.polaris.live.im.sfs.COMMAND_BATCH_COMMAND_ACK
import com.polaris.live.im.sfs.COMMAND_SINGLE_MESSAGE
import com.polaris.live.im.sfs.COMMAND_SYSTEM_MESSAGE
import com.polaris.live.im.sfs.MESSAGE_STATUS_ERROR
import com.polaris.live.im.sfs.SendStatus
import com.polaris.live.im.sfs.bean.chat.ChatAckMessage
import com.polaris.live.im.sfs.bean.chat.ReceiveSingleMessage
import com.polaris.live.im.sfs.core.SmartFoxManager
import com.polaris.live.im.sfs.core.SmartFoxQueueManager
import com.polaris.live.utils.LifecycleListenerDispatcher
import kotlinx.coroutines.withContext

/**
 * 管理消息的增删改查
 *
 * @author Created by 半仙 on 2023/8/23/023 11:28
 */
object ImMessageManager {

    private val receiveDispatcher =
        LifecycleListenerDispatcher<SingleMessageReceiveListener>("receiveDispatcher")
    private val sendDispatcher =
        LifecycleListenerDispatcher<SingleMessageSendListener>("sendDispatcher")

    /**
     * 添加消息接收监听
     */
    fun observeReceive(owner: LifecycleOwner, l: SingleMessageReceiveListener) {
        receiveDispatcher.observe(owner, l)
    }

    /**
     * 添加消息发送监听
     */
    fun observeSend(owner: LifecycleOwner, l: SingleMessageSendListener) {
        sendDispatcher.observe(owner, l)
    }

    internal val messageOtherIds = StructUtils.newSaleSet<Long>()

    /**
     * 观察私聊用户
     */
    fun observeSingleUserId(owner: LifecycleOwner, otherId: Long) {
        if (owner.lifecycle.currentState == Lifecycle.State.DESTROYED) {
            return
        }

        messageOtherIds.add(otherId)

        owner.lifecycle.addObserver(object : LifecycleEventObserver {
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    messageOtherIds.remove(otherId)
                }
            }
        })
    }

    suspend fun onReceiveSingleMessage(message: ReceiveSingleMessage) {
        withContext(SmartFoxManager.noticeDispatcher) {
            receiveDispatcher.listeners.forEach { it.onReceiveMessage(message) }
        }
    }

    //插入一条消息
    suspend fun insertMessage(messageEntity: MessageEntity) {
        AppDatabase.instance.messageDao().apply {
            val haveMessage = findMessageByUserIdAndMsgId(UserManager.getUserId(), messageEntity.msgId)
            if (haveMessage == null) {
                val saveMessage = saveMessage(messageEntity)
                if (saveMessage > 0) {
                    val command = messageEntity.command
                    val seqId = messageEntity.seqId
                    if (seqId != null) {
                        ackMessage(command, seqId)
                    }
                }
            }
        }
    }

    suspend fun updateMessage(messageEntity: MessageEntity) {
        AppDatabase.instance.messageDao().saveMessage(messageEntity)
    }

    suspend fun updateMessageAndDispatch(messageEntity: MessageEntity) {
        AppDatabase.instance.messageDao().saveMessage(messageEntity)

        onDispatchSendMessage(messageEntity)
    }

    //修改某条消息的发送状态
    suspend fun updateMessageStateAndDispatch(
        messageEntity: MessageEntity,
        timestamp: Long,
        state: Int,
    ) {
        AppDatabase.instance.messageDao()
            .updateMessageStateByUserIdAndMsgId(UserManager.getUserId(), messageEntity.msgId, timestamp, state)

        onDispatchSendMessage(
            messageEntity.copy(
                timestamp = timestamp,
                state = state
            )
        )
    }

    //修改某条消息的发送状态异常
    suspend fun updateMessageStateErrorAndDispatch(
        messageEntity: MessageEntity,
        timestamp: Long,
        errorCode: Int,
        errorMessage: String,
        isTimeOut: Int? = null,
    ) {
        AppDatabase.instance.messageDao()
            .updateMessageStateErrorByUserIdAndMsgId(
                UserManager.getUserId(),
                messageEntity.msgId,
                timestamp,
                isTimeOut ?: MESSAGE_STATUS_ERROR,
                errorCode,
                errorMessage
            )

        onDispatchSendMessage(
            messageEntity.copy(
                timestamp = timestamp,
                state = MESSAGE_STATUS_ERROR,
                errorCode = errorCode,
                errorMessage = errorMessage
            )
        )
    }

    suspend fun onDispatchSendMessage(messageEntity: MessageEntity) {
        withContext(SmartFoxManager.noticeDispatcher) {
            sendDispatcher.listeners.forEach {
                it.onMessage(messageEntity.state, messageEntity)
            }
        }
    }

    /**
     * ack消息回执
     */
    suspend fun ackMessage(command: String, seqId: Long) {
        if (seqId == -1L) {
            return
        }

        //ack出现错误不影响页面接收，等待下次接收重试
        try {
            val finalCommand = if (command == COMMAND_SYSTEM_MESSAGE) {
                COMMAND_SINGLE_MESSAGE
            } else {
                command
            }

            SmartFoxQueueManager.sendChatMessage(
                COMMAND_BATCH_COMMAND_ACK,
                ChatAckMessage(finalCommand, listOf(seqId))
            )
        } catch (t: Throwable) {
            LogExt.logE(SmartFoxManager.TAG, "ack", t)
        }
    }
}

fun interface SingleMessageReceiveListener {

    /**
     * 接收私聊消息
     */
    @MainThread
    fun onReceiveMessage(message: ReceiveSingleMessage)

}

fun interface SingleMessageSendListener {

    /**
     * 发送私聊消息
     */
    @MainThread
    fun onMessage(@SendStatus state: Int, message: MessageEntity)

}